
#include "pcie.h"
#include <iostream>
#include <string>

using namespace std;

#ifdef __linux__
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <ctype.h>
#include "inno_pcie.h"

#define BUFFER_LEN 1024

CPcieComm::CPcieComm()
{
}

CPcieComm::~CPcieComm() {}

int CPcieComm::pcie_open()
{
    //************************************************************
    // Step1: open device.
    // Use chmod 777 /dev/inno_pcie get access right.
    //************************************************************
    fd = open("/dev/inno_pcie", O_RDWR);
    if (fd < 0)
    {
        printf("pcie:open device error!fd:%d\n", fd);
        return -1;
    }
    else
    {
        printf("pcie:open device success!\n");
    }
    //************************************************************
    // Step2: DMA and C2H initialization.
    //
    //************************************************************
    unsigned long arg = 1;
    int res = ioctl(fd, INNO_INIT, &arg);
    if (res < 0)
    {
        printf("pcie:ioctl cmd1 failed!\n");
        return -1;
    }
    else
    {
        printf("pcie:ioctl cmd1 success!\n");
    }

    return 0;
}

int CPcieComm::pcie_write(UINT addr_offset, BYTE *data, UINT len, string device)
{
    // write data finash signal
    if(addr_offset == 0xFFFFFFFF)
    {
        //************************************************************
        // Step4: send data done signal to risc-v.
        // 
        //************************************************************
        unsigned long arg = MODEL_DATA;
        int res = ioctl(fd,SEND_DATA_DONE,&arg);
        if(res<0)
        {
            printf("pcie:ioctl SEND_DATA_DONE failed!\n");
            return -1;
        }
        else
        {
            printf("pcie:ioctl SEND_DATA_DONE success!\n");
        }
        return len;
    }

    lseek(fd, addr_offset, SEEK_SET);
    int res = write(fd, data,len);
	if(res < 0)
	{
		printf("pcie:write cmd failed!\n");
        return -1;
	}
	else
	{
		printf("pcie:write cmd success!\n");
	}
    return res;
}

int CPcieComm::pcie_read(UINT addr_offset, BYTE *data, UINT &len, std::string device)
{
    
    // check read status
    if(addr_offset == 0xFFFFFFFF) 
    {
        //************************************************************
        // Step5: check muse calculation result.
        // 
        //************************************************************
        unsigned long arg = 4;
        int res = ioctl(fd,DMA_CHECK_RESULT,&arg);
        if(res<0)
        {
            printf("pcie:ioctl SEND_DATA_DONE failed!\n");
            return -1;
        }
        else
        {
            printf("pcie:ioctl SEND_DATA_DONE success!\n");
        }
        //if read dma ready arg == 1
        return arg;
    }


    lseek(fd, addr_offset, SEEK_SET);
    int res = read(fd, data,len);
	if(res < 0)
	{
		printf("pcie:read cmd failed!\n");
        return -1;
	}
	else
	{
		printf("pcie:read cmd success!\n");
	}
    return res;
}

bool CPcieComm::pcie_is_open()
{
    if (fd < 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

int CPcieComm::pcie_close()
{
    if (fd < 0)
    {
    }
    else
    {
        close(fd);
        fd = -1;
    }

    return 0;
}

#endif
